package com.gitee.wsl.statemachine

import com.gitee.wsl.prop.PropContainerImpl
import com.gitee.wsl.statemachine.transition.StateMachineActionFlow
import com.gitee.wsl.statemachine.trigger.SampleActionTrigger
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.flow.MutableStateFlow

class StateMachineContext<A,State>(
    val coroutineScope: CoroutineScope,
    private val stateFlow: MutableStateFlow<State>
) {
    val props = PropContainerImpl()

    val actionTriggerMap = mutableMapOf<State, SampleActionTrigger<State>>()

    val stateFlowList = mutableListOf<StateMachineActionFlow<A, State>>()

    fun transitionTo(state: State) {
        val beforeState = stateFlow.value
        beforeState?.let {
            actionTriggerMap[it]?.leave(it, state)
        }
        val handler = actionTriggerMap[state]
        handler?.before(beforeState, state)
        handler?.entry(beforeState, state)
        stateFlow.value = state
        handler?.after(beforeState, state)
    }

    fun tryActionAuto(action: A): Boolean {
        stateFlow.value?.let {state->
             /*actionTriggerMap[state]?.let { handler->
                 stateFlowList.find { it.fromState == state && it.action == action && handler.tryAction(state,it.toState) }?.let {
                     return true
                 }
             }*/
            return findActionFlowList(state,action) != null
        }
        return false
    }

    fun actionAuto(action: A){
        stateFlow.value?.let {state->
            findActionFlowList(state,action)?.let {
                it.block()
                transitionTo(it.toState)
            }
        }
    }

    //operator fun State.unaryPlus() = transitionTo(this)

    private fun findActionFlowList(state:State,action:A)
             = stateFlowList.find { it.fromState == state && it.action == action && actionTriggerMap[state]?.tryAction(state,it.toState) != false }
}